Flex 4 でオサレなアルファマスク List コンポーネント
Flex 4 コンポーネント拡張の小ネタを紹介します。
アルファマスクは、ブレンドモードを使用することによって実現できます。 マスク対象コンポーネントとマスクの関係を「表示オブジェクトの親子関係」として、マスク対象コンポーネントのブレンドモードを「レイヤー (BlendMode.LAYER) 」、マスクのブレンドモードを「削除 (BlendMode.ERASE) 」と定義することによって、「塗りのアルファ」がマスクとして機能します。
実装コード (AlphaMaskList.as)
package jp.classmethod.sample { import flash.display.BlendMode; import flash.display.GradientType; import flash.display.Graphics; import flash.geom.Matrix; import spark.components.List; import spark.core.SpriteVisualElement; /** <p>maskColors 配列内の各色に対応するアルファ値の配列。有効な値は 0 ~ 1 です。 0 未満の値を指定した場合、デフォルトで 0 が適用されます。1 より大きい値を指定した場合、デフォルトで 1 が適用されます。</p> */ [Style(name="maskAlphas", type="Array", arrayType="int", inherit="no")] /** <p>グラデーションで使用する RGB 16 進カラー値の配列 ( 赤 0xFF0000、青 0x0000FF など )。 最大 15 色まで指定できます。 各色について、maskAlphas スタイルプロパティと maskRatios スタイルプロパティに対応する値を指定してください。 </p> */ [Style(name="maskColors", type="Array", arrayType="int", inherit="no")] /** <p>色分布比率の配列です。0 ~ 255 の範囲の値を指定できます。この値は、100% でサンプリングされる色の幅の割合をパーセントで定義します。 値 0 はグラデーションボックスの左の位置を表し、255 はグラデーションボックスの右の位置を表します。</p> */ [Style(name="maskRatios", type="Array", arrayType="int", inherit="no")] /** * <p>オサレなアルファマスク List コンポーネント</p> * @author taiga */ public class AlphaMaskList extends List { /** <p>mask alphas</p> */ protected var _maskAlphas:Array; /** <p>mask colors</p> */ protected var _maskColors:Array; /** <p>mask ratios</p> */ protected var _maskRatios:Array; [SkinPart] /** <p>アルファマスク</p> */ public var alphaMask:SpriteVisualElement; /** <p>コンストラクタ</p> */ public function AlphaMaskList() { super(); setStyle("skinClass", AlphaMaskListSkin); blendMode = BlendMode.LAYER; _maskColors = [0, 0, 0]; _maskAlphas = [1, 0, 1]; _maskRatios = [0, 127, 255]; } /** @private */ protected override function partAdded(partName:String, instance:Object):void { super.partAdded(partName, instance); if(instance == alphaMask) { alphaMask.includeInLayout = false; alphaMask.mouseEnabled = false; alphaMask.blendMode = BlendMode.ERASE; } } /** @private */ protected override function commitProperties():void { super.commitProperties(); var alphas:Array = getStyle("maskAlphas"); var colors:Array = getStyle("maskColors"); var ratios:Array = getStyle("maskRatios"); if(alphas != null) { _maskAlphas = alphas; } if(colors != null) { _maskColors = colors; } if(ratios != null) { _maskRatios = ratios; } } /** @private */ protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); if(alphaMask != null) { var g : Graphics; var m : Matrix; var rad : Number; var w : Number; var h : Number; rad = Math.PI * 0.5; w = unscaledWidth - 16; h = unscaledHeight - 2; m = new Matrix(); m.createGradientBox(w, h, rad); g = alphaMask.graphics; g.clear(); g.beginGradientFill(GradientType.LINEAR, _maskColors, _maskAlphas, _maskRatios, m); g.drawRect(1, 1, w, h); g.endFill(); } } } }
実装コード (AlphaMaskListSkin.mxml)
<?xml version="1.0" encoding="utf-8"?> <s:Skin xmlns:fx = "http://ns.adobe.com/mxml/2009" xmlns:s = "library://ns.adobe.com/flex/spark" minWidth = "112" alpha.disabled = "0.5" blendMode = "normal" > <fx:Metadata> <![CDATA[ [HostComponent("jp.classmethod.sample.AlphaMaskList")] ]]> </fx:Metadata> <s:states> <s:State name="normal" /> <s:State name="disabled" /> </s:states> <s:Rect left="0" right="0" top="0" bottom="0" id="border"> <s:stroke> <s:SolidColorStroke id="borderStroke" weight="1"/> </s:stroke> </s:Rect> <s:Rect id="background" left="1" right="1" top="1" bottom="1" > <s:fill> <s:SolidColor id="bgFill" color="0xFFFFFF" /> </s:fill> </s:Rect> <s:Scroller left="0" top="0" right="0" bottom="0" id="scroller" minViewportInset="1" hasFocusableChildren="false"> <s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer"> <s:layout> <s:VerticalLayout gap="0" horizontalAlign="contentJustify" requestedMinRowCount="5" paddingTop="100" paddingBottom="100" /> </s:layout> </s:DataGroup> </s:Scroller> <s:SpriteVisualElement id="alphaMask" left="0" top="0" right="0" bottom="0" /> </s:Skin>
実装コード (Main.mxml)
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx = "http://ns.adobe.com/mxml/2009" xmlns:s = "library://ns.adobe.com/flex/spark" xmlns:cm = "jp.classmethod.sample.*" fontSize = "30" > <cm:AlphaMaskList width = "300" height = "400" verticalCenter = "0" horizontalCenter = "0" itemRenderer = "spark.skins.spark.DefaultComplexItemRenderer" > <cm:dataProvider> <s:ArrayList> <s:Button label="AAAA" width="100%" height="50" /> <s:Button label="BBBB" width="100%" height="50" /> <s:Button label="CCCC" width="100%" height="50" /> <s:Button label="DDDD" width="100%" height="50" /> <s:Button label="EEEE" width="100%" height="50" /> <s:Button label="FFFF" width="100%" height="50" /> <s:Button label="GGGG" width="100%" height="50" /> <s:Button label="HHHH" width="100%" height="50" /> <s:Button label="IIII" width="100%" height="50" /> <s:Button label="JJJJ" width="100%" height="50" /> <s:Button label="KKKK" width="100%" height="50" /> <s:Button label="LLLL" width="100%" height="50" /> <s:Button label="MMMM" width="100%" height="50" /> <s:Button label="NNNN" width="100%" height="50" /> </s:ArrayList> </cm:dataProvider> </cm:AlphaMaskList> </s:Application>
出力結果
出力結果は次の通り
[SWF]http://public-blog-dev.s3.amazonaws.com/wp-content/uploads/2011/09/AlphaMaskListSample.swf,640,480[/SWF]